/*
 * Copyright (c) 2022 Hunan OpenValley Digital Industry Development Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <stdio.h>
#include "cmsis_os2.h"
#include "ohos_run.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "esp_log.h"
#include "driver/gpio.h"

#include "driver/ledc.h"
#include "driver/timer.h"
#include "esp_timer.h"


#define SYS_DELAY_TICKS 200
#define TASK_STACK_SIZE 4096
#define TASK_PRIO 25

#define GPIO_LED_R    GPIO_NUM_2
#define GPIO_LED_Y    GPIO_NUM_23
#define GPIO_LED_G    GPIO_NUM_22
#define GPIO_BUZZ     GPIO_NUM_15

static uint32_t delay_ms = 1000; // 初始延迟设置为1秒
esp_timer_handle_t gTimerHandle;

static void timer_callback(void *arg)
{
    static uint8_t led_state = 0;
    switch (led_state) {
        case 0:
            gpio_set_level(GPIO_LED_R, 1);
            led_state++;
            break;
        case 1:
            gpio_set_level(GPIO_LED_R, 0);
            gpio_set_level(GPIO_LED_Y, 1);
            led_state++;
            break;
        case 2:
            gpio_set_level(GPIO_LED_Y, 0);
            gpio_set_level(GPIO_LED_G, 1);
            led_state++;
            break;
        case 3:
            gpio_set_level(GPIO_LED_G, 0);
            led_state = 0; // 重置状态
            break;
    }

    // 减少延迟时间
    if (delay_ms > 10) { // 设置最小延迟时间
        delay_ms -= 50; // 每次减少50ms
    }
    else
    {
        delay_ms = 1000;
    }

    esp_timer_start_once(gTimerHandle, delay_ms * 1000); // 转换为微秒
}

static void gpio_test(void)
{
    // 初始化GPIO
    // 配置为输出
    gpio_config_t gpior = {
        .intr_type = GPIO_INTR_DISABLE, //关闭中断
        .mode = GPIO_MODE_OUTPUT,        //输出模式
        .pin_bit_mask = 1ULL << GPIO_LED_R,  //16引脚
        .pull_down_en = GPIO_PULLDOWN_DISABLE,  //关闭下拉
        .pull_up_en = GPIO_PULLUP_ENABLE        //开启上拉
    };

    gpio_config(&gpior);

    //配置为输出
    gpio_config_t gpiog = {
        .intr_type = GPIO_INTR_DISABLE, //关闭中断
        .mode = GPIO_MODE_OUTPUT,        //输出模式
        .pin_bit_mask = 1ULL << GPIO_LED_Y,  //16引脚
        .pull_down_en = GPIO_PULLDOWN_DISABLE,  //关闭下拉
        .pull_up_en = GPIO_PULLUP_ENABLE        //开启上拉
    };

    gpio_config(&gpiog);

    //配置为输出
    gpio_config_t gpiob = {
        .intr_type = GPIO_INTR_DISABLE, //关闭中断
        .mode = GPIO_MODE_OUTPUT,        //输出模式
        .pin_bit_mask = 1ULL << GPIO_LED_G,  //16引脚
        .pull_down_en = GPIO_PULLDOWN_DISABLE,  //关闭下拉
        .pull_up_en = GPIO_PULLUP_ENABLE        //开启上拉
    };

    gpio_config(&gpiob);


    //配置为输出
    gpio_config_t gpiobuzz = {
        .intr_type = GPIO_INTR_DISABLE, //关闭中断
        .mode = GPIO_MODE_OUTPUT,        //输出模式
        .pin_bit_mask = 1ULL << GPIO_BUZZ,  //16引脚
        .pull_down_en = GPIO_PULLDOWN_DISABLE,  //关闭下拉
        .pull_up_en = GPIO_PULLUP_ENABLE        //开启上拉
    };

    gpio_config(&gpiobuzz);

    gpio_set_level(GPIO_BUZZ,0);
    printf("gpio init ok!\n");

    // 创建定时器
    esp_timer_create_args_t create_args = {
        .callback = &timer_callback,
        .name = "timer_led",
    };
  
    ESP_ERROR_CHECK(esp_timer_create(&create_args, &gTimerHandle));

    // 启动定时器
    esp_timer_start_once(gTimerHandle, delay_ms * 1000); // 转换为微秒
    printf("timer init ok!");
}

static void gpio_example_task(void)
{
    osThreadAttr_t attr;
    int g_taskID;

    attr.name = "adc_test";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = TASK_STACK_SIZE;
    attr.priority = TASK_PRIO;
    g_taskID = osThreadNew((osThreadFunc_t)gpio_test, NULL, &attr);
    if (g_taskID == NULL) {
        printf("Failed to create Test GPIO thread!\n");
    }
}
OHOS_APP_RUN(gpio_example_task);